/// 1. 泛型时具体类型或者其他属性的抽象代替，用于减少代码重复
/// 2. 在函数定义中使用泛型
/// 3. 在结构体中使用泛型
/// 4. 在枚举中使用泛型
/// 5. 在方法中使用泛型
/// 6. 总结：使用泛型并不会造成程序性能上的损失，rust通过在编译时进行泛型代码的单态化来保证效率。
/// 单台化时，通过填充编译时使用的具体类型，将通用代码转换未特定代码的过程
// for i32
fn largest_i32(list: &[i32]) -> i32 {
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

// for char
fn largest_char(list: &[char]) -> char {
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}
// 如上两个方法，逻辑一样就是类型不一样，导致同一逻辑写了两边，特别耗时，为此推出泛型
// 函数中使用泛型
// fn largest<T: PartialOrd + Copy> (list: &[T]) -> T{ // 也可可以这么写
fn largest<T> (list: &[T]) -> T
where T: PartialOrd + Copy { //T: PartialOrd + Copy允许类型的简单复制而不需要移动
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}
// 结构体中使用泛型
#[derive(Debug)]
struct Point<T> {
    x: T,
    y: T,
}

#[derive(Debug)]
struct Point2<T, U> {
    x: T,
    y: U,
}

// 枚举当中使用泛型 下面两个都是标准库中提供的
enum Option<T> {
    Some(T),
    None,
}
enum Result<T, E> {
    Ok(T),
    Err(E),
}
// 在方法中使用泛型
#[derive(Debug)]
struct Point3<T, U> {
    x: T,
    y: U,
}
// impl就是一个方法，通常结合结构体一起使用
/***
fn creat_point<V, W> (self, other: Point3<V, W>) -> Point3<T, W >
self:
    self 表示调用这个方法的 Point3 实例。
    1. 它指向了当前的对象，让你能够访问这个对象的属性（比如 x 和 y）。
    2. 当你在方法中使用 self.x 时，你实际上是在访问调用该方法的实例的 x 值。

other:
    other 是方法的参数，表示传入的另一个 Point3 实例。
    1. 这个实例可以与 self 有不同的类型，或者可以是相同的类型，取决于你如何使用这个方法。
    2. 在方法内部，你使用 other.y 来访问这个传入实例的 y 值。
 */
impl<T, U> Point3<T, U> {
    fn creat_point<V, W> (self, other: Point3<V, W>) -> Point3<T, W > {
        Point3 {
            x: self.x,
            y: other.y,
        }
    }
    fn get_x(&self) -> &T {
        &self.x
    }
    fn get_y(&self) -> &U {
        &self.y
    }
}
fn main() {
    println!("========================方法中的泛型======================================");
    let med = Point3{x: 1, y: 2.7};
    let med1 = Point3{x: "hello", y: 'C'};
    println!("{}", med.get_x());
    println!("{}", med.get_y());
    println!("{:#?}", med);

    let med2 = med1.creat_point(med);
    println!("x = {}, y = {}", med2.x, med2.y);

    // 调用结构体
    println!("========================多泛型======================================");
    let integer1 = Point2 { x: 5, y: 1 };
    println!("x = {}, y = {}", integer1.x, integer1.y);
    println!("Point = {:?}", integer1);

    let f_s = Point2 { x: 1.22, y: "hahah"};
    println!("x = {}, y = {}", f_s.x, f_s.y);
    println!("Point = {:?}", f_s);

    println!("========================单泛型======================================");
    let integer = Point { x: 5, y: 10 };
    println!("x = {}, y = {}", integer.x, integer.y);
    println!("Point = {:?}", integer);

    let float = Point { x: 1.22, y: 2.23};
    println!("x = {}, y = {}", float.x, float.y);
    println!("Point = {:?}", float);
    println!("========================函数中泛型====================================");
    // 调用泛型
    let number_list = vec![34, 50, 25, 100, 65, 101];
    let result = largest(&number_list);
    println!("max_number = {}", result);

    let char_list = vec!['y', 'm', 'a', 'q', 'z'];
    let result = largest(&char_list);
    println!("max_chars = {}", result);

    // 调用方法
    let number_list = vec![34, 50, 25, 100, 65];
    let result = largest_i32(&number_list);
    println!("max_number = {}", result);

    let char_list = vec!['y', 'm', 'a', 'q'];
    let result = largest_char(&char_list);
    println!("max_chars = {}", result);
}
